package me.ingxin.android.badge

import android.graphics.*
import android.graphics.drawable.Drawable
import kotlin.math.abs
import kotlin.math.roundToInt

/**
 * Created by ingxin on 2022/12/16
 * 绘制角标
 */
class BadgeDrawable : Drawable() {

    /**背景颜色*/
    var backgroundColor = Color.RED

    /**边框宽度，单位px*/
    var borderWidth = 0

    /**边框颜色*/
    var borderColor = Color.WHITE

    /**角标数*/
    var number = 0

    /**角标最大值,超过最大值显示+号*/
    var maxNumber = Int.MAX_VALUE

    /**角标字体颜色*/
    var textColor = Color.WHITE
        set(value) {
            textPaint.color = value
            field = value
        }

    /**背景变形为圆角矩形时，字体水平间距，单位px*/
    var roundPaddingHorizontal = 12

    /**背景变形为圆角矩形时，字体垂直间距，单位px*/
    var roundPaddingVertical = 6

    /**背景为圆形时字体padding值*/
    var circlePadding = 16

    /**角标字体大小，单位px*/
    var textSize = 32
        set(value) {
            textPaint.textSize = value.toFloat()
            field = value
        }

    /**角标字体是否加粗*/
    var textBold = true
        set(value) {
            textPaint.isFakeBoldText = value
            field = value
        }

    private val textPaint = Paint().apply {
        isAntiAlias = true
        textSize = this@BadgeDrawable.textSize.toFloat()
        color = textColor
        isFakeBoldText = textBold
    }
    private val paint = Paint().apply { isAntiAlias = true }
    private val tempRectF = RectF()
    private var dotModel = false
    var radius = 10
        private set

    /**
     * 开启红点模式，角标文本关闭，此时角标显示为红点。
     * 见[enableBadgeText]
     * @param radius 红点半径
     */
    fun enableDot(radius: Int) {
        this.dotModel = true
        this.radius = radius
    }

    /**
     * 开启角标文本模式，红点模式关闭，此时角标显示文字。
     * 见[enableDot],默认开启文本模式
     */
    fun enableBadgeText() {
        this.dotModel = false
    }

    private fun getTextWidth(): Int {
        val str = getText() ?: return 0
        return textPaint.measureText(str).roundToInt()
    }

    private fun getTextHeight(): Int {
        val metrics = textPaint.fontMetrics
        return (metrics.descent - metrics.ascent).toInt()
    }

    private fun getText(): String? {
        if (dotModel) {
            return null
        }
        //文字宽度
        return if (number > maxNumber) {
            "${maxNumber}+"
        } else {
            number.toString()
        }
    }

    override fun getIntrinsicWidth(): Int {
        return if (dotModel) {
            2 * radius
        } else {
            val textW = getTextWidth()
            val textH = getTextHeight()
            if (textW <= textH) {
                //圆形
                textH + circlePadding
            } else {
                //圆角矩形
                getTextWidth() + roundPaddingHorizontal * 2
            }
        }
    }

    override fun getIntrinsicHeight(): Int {
        return if (dotModel) {
            2 * radius
        } else {
            val textW = getTextWidth()
            val textH = getTextHeight()
            if (textW <= textH) {
                //圆形
                textH + circlePadding
            } else {
                //圆角矩形
                getTextHeight() + roundPaddingVertical * 2
            }
        }
    }

    override fun draw(canvas: Canvas) {
        //获取setBounds设置的值
        val r = bounds
        val count = canvas.save()
        canvas.translate(r.left.toFloat(), r.top.toFloat())
        onDraw(canvas)
        canvas.restoreToCount(count)
    }

    private fun onDraw(canvas: Canvas) {
        initBgPaint()

        //圆心
        val cx = intrinsicWidth / 2f
        val cy = intrinsicHeight / 2f

        var paddingVertical = 0

        //绘制背景
        if (dotModel) {
            canvas.drawCircle(cx, cy, radius.toFloat(), paint)
        } else if (intrinsicWidth <= intrinsicHeight) {
            canvas.drawCircle(cx, cy, intrinsicHeight / 2f, paint)
        } else {
            val cornerRadius = intrinsicHeight / 2f
            tempRectF.set(0f, 0f, bounds.width().toFloat(), bounds.height().toFloat())
            canvas.drawRoundRect(tempRectF, cornerRadius, cornerRadius, paint)
            //绘制圆角矩形时采用额外的水平间距
            paddingVertical = roundPaddingVertical
        }

        //绘制边框
        val bw = borderWidth / 2
        if (bw > 0) {
            initBorderPaint()
            if (dotModel) {
                canvas.drawCircle(cx, cy, radius.toFloat(), paint)
            } else if (intrinsicWidth <= intrinsicHeight) {
                canvas.drawCircle(cx, cy, intrinsicHeight / 2f, paint)
            } else {
                val cornerRadius = intrinsicHeight / 2f
                tempRectF.set(0f, 0f, bounds.width().toFloat(), bounds.height().toFloat())
                canvas.drawRoundRect(tempRectF, cornerRadius, cornerRadius, paint)
            }
        }

        //绘制文本
        getText()?.let {
            val x = (intrinsicWidth - getTextWidth()) / 2f
            val availableHeight = (intrinsicHeight - paddingVertical * 2)
            val y =
                (availableHeight - getTextHeight()) / 2f + abs(textPaint.fontMetrics.ascent) + paddingVertical
            canvas.drawText(it, x, y, textPaint)
        }
    }

    private fun initBorderPaint() {
        with(paint) {
            isAntiAlias = true
            color = borderColor
            strokeWidth = borderWidth.toFloat()
            style = Paint.Style.STROKE
        }
    }

    private fun initBgPaint() {
        with(paint) {
            isAntiAlias = true
            color = backgroundColor
            style = Paint.Style.FILL
            strokeWidth = 0f
        }
    }


    override fun setAlpha(alpha: Int) {
        textPaint.alpha = alpha
        paint.alpha = alpha
    }

    override fun setColorFilter(colorFilter: ColorFilter?) {
        //do nothing
    }

    override fun getOpacity(): Int {
        return PixelFormat.TRANSLUCENT
    }

}